electron + react快速搭建一个桌面端应用

您所在的位置:网站首页 ant messenger下载官方下载 electron + react快速搭建一个桌面端应用

electron + react快速搭建一个桌面端应用

2023-03-15 16:28| 来源: 网络整理| 查看: 265

在这里插入图片描述

前言

头两天接到一个小伙伴的请求帮助哈,他想在electron + react 实现的界面中,通过一个图片或者视频,点击下载按钮然后把资源下载到本地,下次再打开的时候读取本地的数据,这个功能在我们生活中很常见,用的最多的就是QQ, 微信这类实时通信的软件了。

这个问题本身不复杂,但是难就难在怎么去读取本地地址呢,以及存储呢?

如果对elelctron的基础没有一个认知的话,那么无疑这个问题还是有些不好处理。

所以本篇笔记就着重讲解一下关于electron + react 创建一个基础项目的流程以及注意事项。

如果你问为什么不把上面的那个问题给解决掉,那是因为已经有前人把这个问题给处理过了【前人文章】,所以不再赘述。

功能实现 找一块空地

俗话说,建房子总的先找块地吧,不然怎么创建呢,对吧。

那么找一个你喜欢或者习惯的目录去创建一个空文件夹,名称自己想一个,只要自己懂就行(正式项目建议语义化,私人的随意),毕竟以后的项目都是在这个目录下。

可以鼠标右键创建,也可以命令行创建,您高兴就好,随您的意。

具体操作太简单,不讲了。

初始化一个package.json

在上面创建的目录下打开shell命令窗口,在命令行中输入:

npm init

然后在窗口中依据提示填写相关信息即可,这样子就能够在根目录下得到一个package.json文件。

安装Electron 下载Electron依赖 yarn add electron 根目录创建 main.js 文件及具体内容 const { app, BrowserWindow, ipcMain } = require('electron') const path = require('path') const createWindow = () => { const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, contextIsolation: false, preload: path.join(__dirname, 'preload.js') } }) // 显示入口文件内容 mainWindow.loadFile('public/index.html') // 打开调试模式 mainWindow.webContents.openDevTools(); } app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() }) 根目录下package.json文件 { ... "main": "main.js", "scripts": { ... } } 根目录下创建 index.html 文件及具体内容 DOCTYPE html> 你好! 你好! 我们正在使用 Node.js , Chromium , 和 Electron . 根目录下创建 preload.js 文件及具体内容 window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const dependency of ['chrome', 'node', 'electron']) { replaceText(`${dependency}-version`, process.versions[dependency]) } }) package.json稍作修改 "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "el": "electron .", }, 运行命令 yarn el 运行效果 在这里插入图片描述 安装React

注意:这一步的所有操作都是在上面electron的基础上进行进一步的修改操作,没有新起项目。

下载 React 依赖

可以通过create-react-app实现 create-react-app [项目名称] 可以在package.json中指定使用react相关版本(本次采用) "dependencies": { ... "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", ... },

根目录创建react相关目录 只要写过vue或者react的都知道,前端页面相关文件都是在根目录src目录下,所以此处我们也不例外,同样在根目录下创建src目录,用于存放前端界面相关逻辑文件。

然后再这个目录下创建界面入口文件App.jsx,具体内容如下:

import React, { useEffect } from 'react'; import { Button } from 'antd'; const App = () => { return ( 11111112224455 qqqq ); } export default App;

package.json稍作修改

"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "el": "electron .", "start:web": "react-scripts start", },

运行命令

yarn start:web

运行效果 在这里插入图片描述 通过与上面electron目录运行结果对比,会发现缺少Node.js , Chromium , 和 Electron .对应的版本号,这是因为react是直接运行在浏览器端,浏览器是不能访问node相关的一部分api所导致的。

功能拆分

上面两个项目都能够正常跑起来了,但是还达不到初始目标,希望的是electron与react能够结合在一起使用,那怎么操作呢?不着急,请接着往下看。

把electron 和 react 分别用各自的目录存放,公共文件单独找个文件放。

基于以上目的,把上面的两个文件给合并抽离,形成最终文件目录,如下图:

在这里插入图片描述

直接这样放置,就能够跑起来吗?

简直不要太天真 O(∩_∩)O哈哈~

目录结构发生变化并且还要把 electron 和 react 结合起来使用,还要实现react项目代码修改,桌面端应用界面也要跟着修改(想想react都有哪些特性)还要实现react界面读取 / 操作系统资源功能

既然如此就继续改改,以期能够实现定下的目标。说到这里就要明白项目是怎么运行的,入口在哪里,运行命令在哪里等等。

废话不多说,请接着往下看。

package.json 文件修改

// 由原来的 main.js 改成如下,这是 electron 运行入口文件 "main": "electron/main.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "el": "electron .", "start:web": "react-scripts start" },

electron - main.js 文件修改

... const createWindow = () => { const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, contextIsolation: false, preload: path.join(__dirname, 'preload.js') } }) /* 以前项目运行的仅仅是一个固定的html文件,现在要结合react,所以此处加载的是一个运行地址; 此处可以通过环境去配置具体加载什么页面; 加载这个地址,必须要让这个地址的项目运行起来,否则桌面端会出现白屏。 */ // mainWindow.loadFile('public/index.html') 【废弃不用】 mainWindow.loadURL('http://localhost:3000/') // 打开调试控制台 mainWindow.webContents.openDevTools(); } ...

react 运行根目录 index.html 文件修改

DOCTYPE html> 你好! 你好! 我们正在使用 Node.js , Chromium , 和 Electron .

接下来就看看修改后的运行效果

在这里插入图片描述

能够看到浏览器端和桌面端基本一致,至于蓝色圆圈圈起来部分的版本号在浏览器没有显示出来,则是因为浏览器不支持NodeJs的一些api,至于原因这大概率是处于浏览器安全机制的考虑,具体原因可以自行查阅相关文档,这里就不再详述。

命令一把梭

通过以上方式基本就实现了一个 Electron + React 的桌面端项目,但是就这个运行方式感觉还是不太安逸,非常的麻烦,具体问题如下:

需要跑两个命令关掉 electron 窗口后,端口仍被占有的情况需要 3000 端口跑起来了再刷新一下 electron 才会有内容浏览器会打开一个 3000 端口的 tab 页, electron 会弹出加载了3000端口内容的窗口,理想状态下只需要保留 electron 中的窗口就好了

根据上面4点问题,也不是没有办法解决,一把梭打开应用完全没有问题。

请看具体实现方式:

下载 npm 库 concurrently,这个主要是解决上面第一和第二个问题,同时同步,一次可以完美的运行多个命令。下载 npm 库 wait-on 字面意思,就是等待什么执行完之后再执行什么命令,解决我们的第三个问题。下载 npm 库 cross-env, 这个大家应该是很熟悉的,经常有用到的。主要解决一些环境变量的问题,但是这次我们使用它是为了利用它的 BROWSER=none 属性来解决上面提到的第四个问题,不打开浏览器中的 tab 页。

综上所述,最后修改package.json文件的运行命令。

"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "el": "electron .", "start:web": "react-scripts start", "start": "concurrently \"(cross-env BROWSER=none react-scripts start)\" \"(wait-on http://localhost:3000/ && electron .)\"" }, 主进程与渲染进程通信

最后,说一下主进程与渲染进程之间的通信问题,有人可能要问,啥是主进程,啥是渲染进程?

这里我就说一下我个人的理解,如有不正确,请评论指正。

主进程:electron 下main.js运行的这个文件,主要管理桌面端运行相关的事件,例如:

创建桌面端窗口;创建弹框窗口;读取本地系统文件等信息加载资源等运行shell打开第三方软件放入托盘等相关事件其他 综上所述,全是与运行平台系统相关的操作,平台例如:windows, OSX, linux。

渲染进程:主要就是界面中能够看到的界面。例如我们这个demo中src目录下的App.js 和 public目录下的index.html。

既然搞明白了主进程与渲染进程,那么我们再将代码给修改修改。

主进程 - main.js

const createWindow = () => { const mainWindow = new BrowserWindow({ ... webPreferences: { nodeIntegration: true, // 此处需要打开,否则调用node相关api会报错 ... } }) } // 这是一个订阅与发布模式 ipcMain.on('sendMsg', (e, params) => { // 接收数据 console.log('这是我接收到的数据::',e, params) console.log('可以获取项目文件地址::', app.getAppPath()) })

渲染进程 - App.jsx(App.jsx属于渲染进程,但是不等于渲染进程,这是一个从属关系)

import React, { useEffect } from 'react'; import { Button } from 'antd'; // 此处需要特别注意,很重要 const {ipcRenderer} = window.require('electron') const App = () => { return ( 11111112224455 // 发送数据 ipcRenderer.send('sendMsg', {a:10}) }}>qqqq ); } export default App;

如上方式就实现了主进程与渲染进程之间的数据通信,接下来请看运行效果:

在这里插入图片描述 在这里插入图片描述

注意:在主进程打印输出的文件,不会在桌面端控制台输出,只会在命令行窗口中打印输出。

关于渲染进程中使用electron相关api,这里特别说明一下,如果不熟悉这块,很容易踩坑。

报错 fs.existsSync is not a function

报错原因: 因为webpack默认产出目标是web平台的 js,其混淆了nodejs的标准模块系统,导致引入nodejs的模块时出现问题。

解决方式: 即通过使用window.require代替require来引入electron,因为前者不会被webpack编译,在渲染进程require关键字就是表示node模块的系统;

在浏览器环境中使用 nodejs api electron将nodejs api挂载在了window对象上,来与底层进行通信,所以需要调用window上的require函数来引入 nodejs 包。

const electron = window.require('electron') const process = window.require('process') const fs = window.require('fs') const Https = window.require('https')

在浏览器环境中使用app对象 在electron主进程中使用app对象直接require electron就行了

const { app } = require('electron')

在渲染进程中使用app对象则需要这样引入:

const electron = window.require('electron'); const app = electron.remote.app;


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3